Skip to content

refactor(websocket): extract setupNewPtyEntry phases into helpers#145

Merged
almogdepaz merged 4 commits into
mainfrom
fix/antipattern-cleanup
May 18, 2026
Merged

refactor(websocket): extract setupNewPtyEntry phases into helpers#145
almogdepaz merged 4 commits into
mainfrom
fix/antipattern-cleanup

Conversation

@almogdepaz
Copy link
Copy Markdown
Owner

Extracts the 478-LOC setupNewPtyEntry god function into four module-level helpers driven by a shared PtyEntryContext. Pure refactor, zero behavior changes.

Helpers

  • waitForResizeSettle(ctx, initialSize) — pre-snapshot client-resize debounce loop. Returns settled size or null on bail.
  • waitForOutputQuiescence(ctx, pendingSize) — applies settled dims, then observes broker output until quiet (so SIGWINCH redraw lands in the snapshot, not the live replay). Returns final applied size or null.
  • sendSnapshotPrefill(ctx, appliedSize, prefillMode) — fetches broker snapshot, chunked send to viewer, returns prefillSeq for live-subscribe sinceSeq.
  • subscribeWithCoalescing(ctx, prefillSeq) — live data sub with adaptive coalescing + lifecycle sub + teardown wiring.

Context

interface PtyEntryContext {
  readonly entry: PtyEntry;
  readonly session: string;
  readonly ws: WebSocket;
  readonly backend: SessionBackend & PtyBackendMethods;
  readonly requestedSize: { current: { cols: number; rows: number } | null };
}

requestedSize is a holder cell (not a plain field) because the outer ws message handler reassigns it AFTER helpers capture the context — they need to see the latest value on every poll.

Numbers

  • setupNewPtyEntry: 478 → 213 LOC
  • attachStreamingBackend orchestrator: 80 LOC (sequencing only)
  • file net +24 LOC (helper signatures + jsdoc)

Drive-by

  • removed dead let pendingPrefillMode (declared, never read)
  • lifted PrefillMode + VALID_PREFILL_MODES to module scope (helpers need them)
  • added explicit return types on attachStreamingBackend + spawnPty
  • extracted PtyEntry interface from inline object-literal type

Verify

  • bunx tsc --noEmit -p . clean
  • bun test — 1483 / 1483 pass
  • zero as any introduced
  • deployed locally via scripts/deploy-local.sh

- app-ralph.ts: add RalphLoop/RalphDeps/StartRalphBody interfaces, type all
  function params, replace 5x `as any` with proper DOM types, extract
  getCheckedRadioValue helper to replace `{} as any` radio pattern
- routes.ts: replace 5x `catch (e: any)` with `catch (e: unknown)` + errMsg,
  remove worktree `as any` include check
- websocket.ts: remove `as any` on activePtySessions.set
- backend.ts: add DuplicateSessionError class, replace monkey-patched
  `(err as any).code` pattern
- mock-backend.ts: use DuplicateSessionError for test consistency
- waitForResizeSettle, waitForOutputQuiescence, sendSnapshotPrefill,
  subscribeWithCoalescing as module-level functions
- PtyEntryContext carries shared state (requestedSize as mutable holder
  so outer ws-handler reassignment is visible to helpers)
- orchestrator slimmed to sequencing; setupNewPtyEntry 478->213 LOC
- drop dead pendingPrefillMode var
- 1483 tests pass, tsc clean, no `as any` introduced
@almogdepaz almogdepaz merged commit fabb7e4 into main May 18, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant